Skip to content

Add @groupreduce and @groupscan - #830

Merged
maleadt merged 2 commits into
vc/ki-subgroup-opsfrom
vc/groupreduce
Oct 12, 2026
Merged

maleadt merged 2 commits into
vc/ki-subgroup-opsfrom
vc/groupreduce

Conversation

@vchuravy

@vchuravy vchuravy commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Work-group reductions and scans for @kernel.

  • @groupreduce(op, val, neutral; groupsize): op associative and commutative, result on
    every work-item. @groupscan(op, val, neutral; groupsize, inclusive = true): associative
    op, in the order of @index(Local, Linear).
  • Collectives like @synchronize: statements of their own, reached by the whole workgroup.
    The split makes padding work-items take part, contributing neutral without evaluating
    val; neutral is evaluated once, and val converted to its type before the call.
  • groupsize (keyword only) bounds a dynamic workgroup size, for the local memory.
  • On backends with sub-groups, @groupreduce reduces each sub-group with
    KernelInterface.sub_group_reduce first. KernelAbstractions picks this from the backend's
    capabilities, carried in the kernel's CompilerMetadata (only for kernels that use
    collectives), for the types the backend can shuffle. It needs neither linear nor
    independent sub-groups.

Documented in the manual under Reductions and scans, with an entry in the 0.10 release notes.

Depends on #831.

On backends without sub-group support, or for types they can't shuffle, both use local memory. On Metal, that path needs GPUCompiler 2.13.4 (JuliaGPU/GPUCompiler.jl#1005, fixing #1004); with older versions the affected test launches are marked broken while they fail to compile.

@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark Results

Show table
main bdd7853... main / bdd7853...
const/@Const/Float32/262144 0.638 ± 0.022 ms 0.64 ± 0.02 ms 0.998 ± 0.047
const/@Const/Float32/65536 0.196 ± 0.015 ms 0.22 ± 0.011 ms 0.894 ± 0.082
const/@Const/Float64/262144 0.834 ± 0.03 ms 0.834 ± 0.015 ms 1 ± 0.04
const/@Const/Float64/65536 0.362 ± 0.018 ms 0.367 ± 0.014 ms 0.985 ± 0.06
const/unmarked/Float32/262144 2.35 ± 0.025 ms 2.32 ± 0.012 ms 1.01 ± 0.012
const/unmarked/Float32/65536 0.622 ± 0.029 ms 0.624 ± 0.023 ms 0.998 ± 0.059
const/unmarked/Float64/262144 3.43 ± 0.029 ms 3.12 ± 0.034 ms 1.1 ± 0.015
const/unmarked/Float64/65536 0.811 ± 0.016 ms 0.815 ± 0.02 ms 0.995 ± 0.031
dgsem/2D/Float32/fluxdiff/element 0.563 ± 0.022 ms 0.575 ± 0.02 ms 0.978 ± 0.052
dgsem/2D/Float32/fluxdiff/node E=8 0.793 ± 0.021 ms 0.806 ± 0.021 ms 0.984 ± 0.037
dgsem/2D/Float32/fluxdiff/node halfsweep E=8 0.59 ± 0.02 ms 0.578 ± 0.022 ms 1.02 ± 0.051
dgsem/2D/Float32/fluxdiff/node halfsweep v-last E=8 0.61 ± 0.034 ms 0.594 ± 0.02 ms 1.03 ± 0.067
dgsem/2D/Float32/weak/element 0.212 ± 0.019 ms 0.222 ± 0.0044 ms 0.954 ± 0.088
dgsem/2D/Float32/weak/element private 0.215 ± 0.014 ms 0.223 ± 0.014 ms 0.964 ± 0.087
dgsem/2D/Float32/weak/node localmem E=1 0.188 ± 0.0056 ms 0.195 ± 0.026 ms 0.966 ± 0.13
dgsem/2D/Float32/weak/node localmem E=8 0.186 ± 0.026 ms 0.184 ± 0.026 ms 1.01 ± 0.2
dgsem/2D/Float32/weak/node localmem v-last E=1 0.272 ± 0.025 ms 0.273 ± 0.026 ms 0.994 ± 0.13
dgsem/2D/Float32/weak/node localmem v-last E=8 0.249 ± 0.012 ms 0.248 ± 0.022 ms 1 ± 0.1
dgsem/2D/Float32/weak/node recompute E=8 0.517 ± 0.025 ms 0.52 ± 0.018 ms 0.996 ± 0.059
dgsem/2D/Float64/fluxdiff/element 0.591 ± 0.024 ms 0.6 ± 0.021 ms 0.985 ± 0.053
dgsem/2D/Float64/fluxdiff/node E=8 0.799 ± 0.019 ms 0.808 ± 0.0073 ms 0.989 ± 0.026
dgsem/2D/Float64/fluxdiff/node halfsweep E=8 0.634 ± 0.015 ms 0.608 ± 0.021 ms 1.04 ± 0.044
dgsem/2D/Float64/fluxdiff/node halfsweep v-last E=8 0.639 ± 0.027 ms 0.638 ± 0.026 ms 1 ± 0.059
dgsem/2D/Float64/weak/element 0.229 ± 0.018 ms 0.249 ± 0.017 ms 0.918 ± 0.097
dgsem/2D/Float64/weak/element private 0.243 ± 0.016 ms 0.252 ± 0.015 ms 0.964 ± 0.085
dgsem/2D/Float64/weak/node localmem E=1 0.195 ± 0.016 ms 0.216 ± 0.027 ms 0.903 ± 0.13
dgsem/2D/Float64/weak/node localmem E=8 0.19 ± 0.026 ms 0.213 ± 0.027 ms 0.89 ± 0.17
dgsem/2D/Float64/weak/node localmem v-last E=1 0.264 ± 0.014 ms 0.28 ± 0.022 ms 0.943 ± 0.089
dgsem/2D/Float64/weak/node localmem v-last E=8 0.256 ± 0.02 ms 0.26 ± 0.022 ms 0.985 ± 0.11
dgsem/2D/Float64/weak/node recompute E=8 0.653 ± 0.016 ms 0.655 ± 0.022 ms 0.998 ± 0.041
dgsem/3D/Float32/fluxdiff/element 1.93 ± 0.021 ms 1.93 ± 0.0055 ms 1 ± 0.011
dgsem/3D/Float32/fluxdiff/node E=2 3.48 ± 0.12 ms 3.3 ± 0.051 ms 1.05 ± 0.04
dgsem/3D/Float32/fluxdiff/node halfsweep E=1 2.39 ± 0.014 ms 2.39 ± 0.013 ms 0.999 ± 0.0082
dgsem/3D/Float32/fluxdiff/node halfsweep v-last E=1 2.03 ± 0.02 ms 2 ± 0.011 ms 1.01 ± 0.012
dgsem/3D/Float32/weak/element 0.672 ± 0.015 ms 0.676 ± 0.021 ms 0.994 ± 0.038
dgsem/3D/Float32/weak/element private 0.709 ± 0.014 ms 0.711 ± 0.023 ms 0.998 ± 0.037
dgsem/3D/Float32/weak/node localmem E=1 0.687 ± 0.023 ms 0.69 ± 0.03 ms 0.996 ± 0.055
dgsem/3D/Float32/weak/node localmem E=2 0.733 ± 0.012 ms 0.748 ± 0.022 ms 0.98 ± 0.033
dgsem/3D/Float32/weak/node localmem v-last E=1 0.925 ± 0.0056 ms 0.902 ± 0.0087 ms 1.03 ± 0.012
dgsem/3D/Float32/weak/node localmem v-last E=2 1.03 ± 0.0035 ms 1.04 ± 0.0042 ms 0.994 ± 0.0052
dgsem/3D/Float32/weak/node recompute E=2 2.09 ± 0.0068 ms 2.09 ± 0.014 ms 1 ± 0.0076
dgsem/3D/Float32/weak/slab E=1 2.74 ± 0.011 ms 2.72 ± 0.013 ms 1.01 ± 0.0063
dgsem/3D/Float32/weak/slab E=8 5.66 ± 0.058 ms 5.52 ± 0.053 ms 1.02 ± 0.014
dgsem/3D/Float32/weak/slab double-buffered E=1 1.58 ± 0.03 ms 1.66 ± 0.021 ms 0.95 ± 0.022
dgsem/3D/Float32/weak/slab double-buffered E=8 2.07 ± 0.019 ms 2.08 ± 0.0062 ms 0.999 ± 0.0096
dgsem/3D/Float32/weak/slab double-buffered v-last E=1 1.6 ± 0.015 ms 1.65 ± 0.0097 ms 0.969 ± 0.011
dgsem/3D/Float32/weak/slab double-buffered v-last E=8 2.11 ± 0.029 ms 2.25 ± 0.013 ms 0.939 ± 0.014
dgsem/3D/Float32/weak/slab v-last E=1 2.64 ± 0.011 ms 2.71 ± 0.012 ms 0.973 ± 0.006
dgsem/3D/Float32/weak/slab v-last E=8 5.75 ± 0.084 ms 5.63 ± 0.074 ms 1.02 ± 0.02
dgsem/3D/Float64/fluxdiff/element 1.99 ± 0.019 ms 1.98 ± 0.012 ms 1.01 ± 0.011
dgsem/3D/Float64/fluxdiff/node E=2 3.01 ± 0.055 ms 2.99 ± 0.017 ms 1 ± 0.019
dgsem/3D/Float64/fluxdiff/node halfsweep E=1 2.21 ± 0.038 ms 2.2 ± 0.024 ms 1 ± 0.021
dgsem/3D/Float64/fluxdiff/node halfsweep v-last E=1 2.13 ± 0.023 ms 2.14 ± 0.0091 ms 0.995 ± 0.012
dgsem/3D/Float64/weak/element 0.846 ± 0.0054 ms 0.83 ± 0.015 ms 1.02 ± 0.02
dgsem/3D/Float64/weak/element private 0.853 ± 0.01 ms 0.861 ± 0.016 ms 0.992 ± 0.022
dgsem/3D/Float64/weak/node localmem E=1 0.745 ± 0.02 ms 0.715 ± 0.013 ms 1.04 ± 0.033
dgsem/3D/Float64/weak/node localmem E=2 0.788 ± 0.0098 ms 0.779 ± 0.0064 ms 1.01 ± 0.015
dgsem/3D/Float64/weak/node localmem v-last E=1 0.905 ± 0.0097 ms 0.905 ± 0.0074 ms 1 ± 0.014
dgsem/3D/Float64/weak/node localmem v-last E=2 1.02 ± 0.012 ms 1.04 ± 0.029 ms 0.982 ± 0.03
dgsem/3D/Float64/weak/node recompute E=2 2.25 ± 0.031 ms 2.22 ± 0.018 ms 1.01 ± 0.016
dgsem/3D/Float64/weak/slab E=1 2.78 ± 0.027 ms 2.76 ± 0.053 ms 1.01 ± 0.022
dgsem/3D/Float64/weak/slab E=8 6.35 ± 0.065 ms 6.37 ± 0.095 ms 0.998 ± 0.018
dgsem/3D/Float64/weak/slab double-buffered E=1 1.61 ± 0.017 ms 1.65 ± 0.026 ms 0.977 ± 0.019
dgsem/3D/Float64/weak/slab double-buffered E=8 2.15 ± 0.053 ms 2.07 ± 0.021 ms 1.04 ± 0.027
dgsem/3D/Float64/weak/slab double-buffered v-last E=1 1.67 ± 0.013 ms 1.65 ± 0.014 ms 1.01 ± 0.012
dgsem/3D/Float64/weak/slab double-buffered v-last E=8 2.13 ± 0.026 ms 2.14 ± 0.023 ms 0.994 ± 0.016
dgsem/3D/Float64/weak/slab v-last E=1 2.75 ± 0.024 ms 2.82 ± 0.06 ms 0.976 ± 0.022
dgsem/3D/Float64/weak/slab v-last E=8 6.33 ± 0.073 ms 6.32 ± 0.12 ms 1 ± 0.023
launch/3D static workgroup, dynamic ndrange 10.5 ± 0.67 μs 10.9 ± 9.1 μs 0.961 ± 0.8
launch/3D static workgroup, static ndrange 10.4 ± 1.2 μs 10.6 ± 0.59 μs 0.979 ± 0.12
launch/dynamic workgroup, dynamic ndrange 11.6 ± 0.47 μs 12.1 ± 4 μs 0.959 ± 0.32
launch/dynamic workgroup, dynamic ndrange, workgroupsize given 16.6 ± 0.41 μs 11.9 ± 0.45 μs 1.39 ± 0.063
launch/static workgroup, dynamic ndrange 10.5 ± 0.44 μs 10.8 ± 0.26 μs 0.97 ± 0.047
launch/static workgroup, static ndrange 10.4 ± 0.48 μs 10.8 ± 0.59 μs 0.958 ± 0.069
narrow workgroup/masked/W=16 0.735 ± 0.033 ms 0.736 ± 0.032 ms 0.998 ± 0.062
narrow workgroup/masked/W=4 0.699 ± 0.031 ms 0.684 ± 0.037 ms 1.02 ± 0.072
narrow workgroup/unmasked/W=16 0.435 ± 0.017 ms 0.437 ± 0.017 ms 0.995 ± 0.056
narrow workgroup/unmasked/W=4 0.431 ± 0.019 ms 0.433 ± 0.018 ms 0.997 ± 0.061
partition/dynamic workgroup, dynamic ndrange 0.0623 ± 0.012 μs 0.0607 ± 0.021 μs 1.03 ± 0.41
partition/static workgroup, dynamic ndrange 0.0733 ± 0.012 μs 0.0675 ± 0.012 μs 1.09 ± 0.26
partition/static workgroup, static ndrange 1.55 ± 0.01 ns 1.55 ± 0.01 ns 1 ± 0.0091
saxpy/default/Float16/1024 15.5 ± 2.1 μs 26.8 ± 1.1 μs 0.58 ± 0.082
saxpy/default/Float16/1048576 1.48 ± 0.031 ms 1.48 ± 0.026 ms 0.998 ± 0.027
saxpy/default/Float16/16384 0.0375 ± 0.0016 ms 0.0386 ± 0.016 ms 0.971 ± 0.4
saxpy/default/Float16/2048 17.2 ± 1.6 μs 28.7 ± 0.83 μs 0.598 ± 0.058
saxpy/default/Float16/256 11.3 ± 0.29 μs 17.3 ± 14 μs 0.65 ± 0.51
saxpy/default/Float16/262144 0.412 ± 0.02 ms 0.409 ± 0.019 ms 1.01 ± 0.068
saxpy/default/Float16/32768 0.0994 ± 0.018 ms 0.0987 ± 0.014 ms 1.01 ± 0.23
saxpy/default/Float16/4096 20.7 ± 0.73 μs 21.1 ± 11 μs 0.978 ± 0.51
saxpy/default/Float16/512 11.5 ± 0.49 μs 25.5 ± 15 μs 0.449 ± 0.26
saxpy/default/Float16/64 11.2 ± 0.34 μs 11.2 ± 0.21 μs 0.996 ± 0.036
saxpy/default/Float16/65536 0.138 ± 0.01 ms 0.149 ± 0.015 ms 0.929 ± 0.12
saxpy/default/Float32/1024 14.9 ± 5 μs 26.1 ± 0.94 μs 0.573 ± 0.19
saxpy/default/Float32/1048576 0.899 ± 0.071 ms 0.897 ± 0.087 ms 1 ± 0.13
saxpy/default/Float32/16384 29.8 ± 15 μs 0.0442 ± 0.0016 ms 0.674 ± 0.34
saxpy/default/Float32/2048 27.5 ± 0.92 μs 16.9 ± 1 μs 1.62 ± 0.11
saxpy/default/Float32/256 24.1 ± 14 μs 11.2 ± 0.31 μs 2.15 ± 1.3
saxpy/default/Float32/262144 0.262 ± 0.031 ms 0.261 ± 0.026 ms 1.01 ± 0.16
saxpy/default/Float32/32768 0.0436 ± 0.0023 ms 0.0425 ± 0.0035 ms 1.02 ± 0.1
saxpy/default/Float32/4096 30 ± 1.6 μs 29.1 ± 11 μs 1.03 ± 0.4
saxpy/default/Float32/512 25.4 ± 12 μs 11.9 ± 4.4 μs 2.13 ± 1.2
saxpy/default/Float32/64 11.1 ± 0.22 μs 24 ± 1.9 μs 0.462 ± 0.038
saxpy/default/Float32/65536 0.107 ± 0.018 ms 0.102 ± 0.014 ms 1.04 ± 0.22
saxpy/default/Float64/1024 16.2 ± 0.8 μs 16.2 ± 0.79 μs 0.997 ± 0.069
saxpy/default/Float64/1048576 1.26 ± 0.22 ms 1.26 ± 0.24 ms 1 ± 0.26
saxpy/default/Float64/16384 0.0339 ± 0.0062 ms 0.0335 ± 0.015 ms 1.01 ± 0.48
saxpy/default/Float64/2048 17.1 ± 0.8 μs 25.3 ± 9.3 μs 0.676 ± 0.25
saxpy/default/Float64/256 14.3 ± 2.6 μs 14.5 ± 14 μs 0.987 ± 0.99
saxpy/default/Float64/262144 0.271 ± 0.066 ms 0.275 ± 0.054 ms 0.986 ± 0.31
saxpy/default/Float64/32768 0.0558 ± 0.045 ms 0.0504 ± 0.013 ms 1.11 ± 0.94
saxpy/default/Float64/4096 19.4 ± 1.3 μs 19.9 ± 8.7 μs 0.977 ± 0.44
saxpy/default/Float64/512 15 ± 1.9 μs 24.5 ± 11 μs 0.614 ± 0.28
saxpy/default/Float64/64 11 ± 0.35 μs 11.5 ± 13 μs 0.956 ± 1.1
saxpy/default/Float64/65536 0.122 ± 0.019 ms 0.112 ± 0.019 ms 1.08 ± 0.25
saxpy/static workgroup=(1024,)/Float16/1024 26.7 ± 0.81 μs 15.7 ± 11 μs 1.7 ± 1.2
saxpy/static workgroup=(1024,)/Float16/1048576 1.48 ± 0.029 ms 1.49 ± 0.047 ms 0.992 ± 0.037
saxpy/static workgroup=(1024,)/Float16/16384 0.038 ± 0.002 ms 0.0376 ± 0.001 ms 1.01 ± 0.061
saxpy/static workgroup=(1024,)/Float16/2048 28.3 ± 0.86 μs 28.5 ± 0.99 μs 0.992 ± 0.046
saxpy/static workgroup=(1024,)/Float16/256 24.5 ± 0.97 μs 17.4 ± 13 μs 1.41 ± 1
saxpy/static workgroup=(1024,)/Float16/262144 0.416 ± 0.022 ms 0.413 ± 0.021 ms 1.01 ± 0.075
saxpy/static workgroup=(1024,)/Float16/32768 0.106 ± 0.023 ms 0.0991 ± 0.016 ms 1.06 ± 0.29
saxpy/static workgroup=(1024,)/Float16/4096 31.1 ± 11 μs 20.9 ± 0.78 μs 1.49 ± 0.53
saxpy/static workgroup=(1024,)/Float16/512 11.8 ± 0.83 μs 25.2 ± 1.6 μs 0.467 ± 0.045
saxpy/static workgroup=(1024,)/Float16/64 11.5 ± 0.24 μs 11.6 ± 0.3 μs 0.989 ± 0.033
saxpy/static workgroup=(1024,)/Float16/65536 0.141 ± 0.016 ms 0.146 ± 0.018 ms 0.962 ± 0.16
saxpy/static workgroup=(1024,)/Float32/1024 14.7 ± 0.97 μs 14.7 ± 0.73 μs 0.998 ± 0.083
saxpy/static workgroup=(1024,)/Float32/1048576 0.881 ± 0.092 ms 0.874 ± 0.12 ms 1.01 ± 0.17
saxpy/static workgroup=(1024,)/Float32/16384 29.4 ± 2.1 μs 28.7 ± 1.5 μs 1.02 ± 0.091
saxpy/static workgroup=(1024,)/Float32/2048 16.6 ± 1 μs 16.7 ± 1.1 μs 0.997 ± 0.091
saxpy/static workgroup=(1024,)/Float32/256 11.6 ± 0.25 μs 11.8 ± 0.49 μs 0.987 ± 0.046
saxpy/static workgroup=(1024,)/Float32/262144 0.261 ± 0.032 ms 0.254 ± 0.027 ms 1.03 ± 0.17
saxpy/static workgroup=(1024,)/Float32/32768 0.0445 ± 0.047 ms 0.0449 ± 0.048 ms 0.993 ± 1.5
saxpy/static workgroup=(1024,)/Float32/4096 18.6 ± 0.9 μs 19.8 ± 11 μs 0.938 ± 0.51
saxpy/static workgroup=(1024,)/Float32/512 11.3 ± 4.7 μs 10.8 ± 4.7 μs 1.04 ± 0.62
saxpy/static workgroup=(1024,)/Float32/64 11.7 ± 0.2 μs 11.9 ± 0.27 μs 0.987 ± 0.028
saxpy/static workgroup=(1024,)/Float32/65536 0.105 ± 0.016 ms 0.101 ± 0.018 ms 1.03 ± 0.24
saxpy/static workgroup=(1024,)/Float64/1024 19 ± 9.9 μs 25.7 ± 1.2 μs 0.739 ± 0.39
saxpy/static workgroup=(1024,)/Float64/1048576 1.24 ± 0.22 ms 1.29 ± 0.23 ms 0.962 ± 0.24
saxpy/static workgroup=(1024,)/Float64/16384 0.034 ± 0.0074 ms 0.0336 ± 0.015 ms 1.01 ± 0.51
saxpy/static workgroup=(1024,)/Float64/2048 17.1 ± 0.7 μs 19 ± 9.4 μs 0.901 ± 0.45
saxpy/static workgroup=(1024,)/Float64/256 26.2 ± 0.77 μs 26.3 ± 0.91 μs 0.997 ± 0.045
saxpy/static workgroup=(1024,)/Float64/262144 0.279 ± 0.078 ms 0.28 ± 0.048 ms 0.996 ± 0.33
saxpy/static workgroup=(1024,)/Float64/32768 0.0538 ± 0.017 ms 0.0556 ± 0.049 ms 0.966 ± 0.9
saxpy/static workgroup=(1024,)/Float64/4096 27.9 ± 8.7 μs 28 ± 9.1 μs 0.995 ± 0.45
saxpy/static workgroup=(1024,)/Float64/512 15.3 ± 2.7 μs 16.8 ± 11 μs 0.912 ± 0.6
saxpy/static workgroup=(1024,)/Float64/64 11.9 ± 13 μs 25.9 ± 1.7 μs 0.458 ± 0.5
saxpy/static workgroup=(1024,)/Float64/65536 0.122 ± 0.022 ms 0.118 ± 0.023 ms 1.03 ± 0.27
time_to_load 0.543 ± 0.00093 s 0.547 ± 0.0019 s 0.992 ± 0.0039
main bdd7853... main / bdd7853...
const/@Const/Float32/262144 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/@Const/Float32/65536 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/@Const/Float64/262144 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/@Const/Float64/65536 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/unmarked/Float32/262144 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/unmarked/Float32/65536 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/unmarked/Float64/262144 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/unmarked/Float64/65536 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
dgsem/2D/Float32/fluxdiff/element 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/2D/Float32/fluxdiff/node E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float32/fluxdiff/node halfsweep E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float32/fluxdiff/node halfsweep v-last E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float32/weak/element 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/2D/Float32/weak/element private 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/2D/Float32/weak/node localmem E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float32/weak/node localmem E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float32/weak/node localmem v-last E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float32/weak/node localmem v-last E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float32/weak/node recompute E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float64/fluxdiff/element 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/2D/Float64/fluxdiff/node E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float64/fluxdiff/node halfsweep E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float64/fluxdiff/node halfsweep v-last E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float64/weak/element 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/2D/Float64/weak/element private 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/2D/Float64/weak/node localmem E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float64/weak/node localmem E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float64/weak/node localmem v-last E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float64/weak/node localmem v-last E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/2D/Float64/weak/node recompute E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float32/fluxdiff/element 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/3D/Float32/fluxdiff/node E=2 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float32/fluxdiff/node halfsweep E=1 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float32/fluxdiff/node halfsweep v-last E=1 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float32/weak/element 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/3D/Float32/weak/element private 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/3D/Float32/weak/node localmem E=1 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float32/weak/node localmem E=2 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float32/weak/node localmem v-last E=1 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float32/weak/node localmem v-last E=2 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float32/weak/node recompute E=2 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float32/weak/slab E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float32/weak/slab E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float32/weak/slab double-buffered E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float32/weak/slab double-buffered E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float32/weak/slab double-buffered v-last E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float32/weak/slab double-buffered v-last E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float32/weak/slab v-last E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float32/weak/slab v-last E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float64/fluxdiff/element 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/3D/Float64/fluxdiff/node E=2 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float64/fluxdiff/node halfsweep E=1 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float64/fluxdiff/node halfsweep v-last E=1 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float64/weak/element 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/3D/Float64/weak/element private 10 allocs: 0.219 kB 10 allocs: 0.219 kB 1
dgsem/3D/Float64/weak/node localmem E=1 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float64/weak/node localmem E=2 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float64/weak/node localmem v-last E=1 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float64/weak/node localmem v-last E=2 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float64/weak/node recompute E=2 13 allocs: 0.391 kB 13 allocs: 0.391 kB 1
dgsem/3D/Float64/weak/slab E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float64/weak/slab E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float64/weak/slab double-buffered E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float64/weak/slab double-buffered E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float64/weak/slab double-buffered v-last E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float64/weak/slab double-buffered v-last E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float64/weak/slab v-last E=1 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
dgsem/3D/Float64/weak/slab v-last E=8 10 allocs: 0.234 kB 10 allocs: 0.234 kB 1
launch/3D static workgroup, dynamic ndrange 9 allocs: 0.219 kB 9 allocs: 0.219 kB 1
launch/3D static workgroup, static ndrange 9 allocs: 0.219 kB 9 allocs: 0.219 kB 1
launch/dynamic workgroup, dynamic ndrange 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
launch/dynamic workgroup, dynamic ndrange, workgroupsize given 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
launch/static workgroup, dynamic ndrange 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
launch/static workgroup, static ndrange 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
narrow workgroup/masked/W=16 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
narrow workgroup/masked/W=4 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
narrow workgroup/unmasked/W=16 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
narrow workgroup/unmasked/W=4 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
partition/dynamic workgroup, dynamic ndrange 2 allocs: 0.0625 kB 2 allocs: 0.0625 kB 1
partition/static workgroup, dynamic ndrange 2 allocs: 32 B 2 allocs: 32 B 1
partition/static workgroup, static ndrange 0 allocs: 0 B 0 allocs: 0 B
saxpy/default/Float16/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float16/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float16/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float16/32768 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float16/65536 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float32/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float32/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float32/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float32/32768 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float32/65536 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float64/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float64/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float64/32768 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float64/65536 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float16/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float16/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float16/32768 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float16/65536 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float32/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float32/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float32/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float32/32768 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float32/65536 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float64/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float64/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float64/32768 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float64/65536 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
time_to_load 0.2 k allocs: 11.8 kB 0.2 k allocs: 11.8 kB 1

Benchmark Plots

A plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR.
Go to "Actions"->"Benchmark a pull request"->[the most recent run]->"Artifacts" (at the bottom).

@codecov

codecov Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.36957% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.59%. Comparing base (7615cb3) to head (bdd7853).

Files with missing lines Patch % Lines
src/groupreduction.jl 98.64% 2 Missing ⚠️
src/macros.jl 95.23% 1 Missing ⚠️
Additional details and impacted files
@@                  Coverage Diff                   @@
##           vc/ki-subgroup-ops     #830      +/-   ##
======================================================
+ Coverage               81.31%   82.59%   +1.28%     
======================================================
  Files                      27       28       +1     
  Lines                    2280     2454     +174     
======================================================
+ Hits                     1854     2027     +173     
- Misses                    426      427       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@vchuravy vchuravy changed the title Add @groupreduce and @subgroupreduce Add @groupreduce, @subgroupreduce, @groupscan and @subgroupscan Oct 3, 2026
@vchuravy
vchuravy changed the base branch from main to vc/ki-subgroup-ops October 3, 2026 22:49
@vchuravy
vchuravy added this pull request to stack #834 October 4, 2026 06:46
@vchuravy
vchuravy force-pushed the vc/groupreduce branch 6 times, most recently from 81e4230 to 06fdf57 Compare October 4, 2026 10:43
@vchuravy
vchuravy force-pushed the vc/groupreduce branch 4 times, most recently from 8333aea to 9b20320 Compare October 4, 2026 16:35
@maleadt maleadt mentioned this pull request Oct 10, 2026
@maleadt maleadt changed the title Add @groupreduce, @subgroupreduce, @groupscan and @subgroupscan Add @groupreduce and @groupscan Oct 10, 2026
@maleadt
maleadt force-pushed the vc/groupreduce branch 2 times, most recently from f4fe613 to 14aefd3 Compare October 10, 2026 21:18
vchuravy and others added 2 commits October 12, 2026 18:19
Work-group reductions and scans for `@kernel`, as collectives like `@synchronize`: they are
statements of their own that every work-item of the workgroup reaches, and the split of the
kernel body makes the work-items that pad a partial workgroup take part, contributing the
neutral element without evaluating the value. The value is converted to the type of
`neutral` before the call, so that a union-typed value doesn't split the collective, and
`neutral` is evaluated once. The upper bound of a dynamic workgroup size is the keyword
`groupsize`.

`@groupreduce` needs a commutative operator, `@groupscan` only an associative one, in the
order of `@index(Local, Linear)`. Both use local memory.

Co-authored-by: Tim Besard <tim@juliahub.com>
On backends with sub-groups, `@groupreduce` reduces every sub-group with
`KernelInterface.sub_group_reduce`, which backends can implement natively, and then the
results of the sub-groups. That only relies on the sub-group ids, so it needs neither linear
nor independent sub-groups.

KernelAbstractions picks the algorithm instead of a user-facing option: kernels that use
collectives get the backend's sub-group capabilities in their `CompilerMetadata`, and use
the sub-groups for types the backend can shuffle. Floating-point types need the backend's
support for that type, since a native shuffle may be selected by type alone; other
primitive types and structs are shuffled as packed words. Kernels without collectives don't
query the capabilities.

Co-authored-by: Tim Besard <tim@juliahub.com>
@maleadt
maleadt merged commit daccb07 into main Oct 12, 2026
102 of 191 checks passed
@maleadt
maleadt deleted the vc/groupreduce branch October 12, 2026 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants